#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "additemdialog.h"

#include <campaign.h>
#include <characterclass.h>
#include <dtwentymodel.h>


#include <XmlSerializer.h>


#include <QDebug>
#include <QTreeView>
#include <QMetaProperty>
#include <QBuffer>
#include <QByteArray>
#include <QFileDialog>

namespace
{
static int CAMPAIGN_TYPE_ID;
}


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    CAMPAIGN_TYPE_ID = qRegisterMetaType<Campaign>("Campaign");

    ui->setupUi(this);
    ui->treeView->setModel(new DTwentyModel(this));
    ui->treeView->header()->setResizeMode(QHeaderView::ResizeToContents);
    ui->treeView->header()->setStretchLastSection(false);

    connect(ui->treeView->model(), SIGNAL(layoutChanged()), this, SLOT(onModelChanged()));
    connect(ui->treeView->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(onModelChanged()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onModelChanged()
{
    ui->plainTextEdit->clear();

    ItemTreeModel* model = qobject_cast<ItemTreeModel*>(ui->treeView->model());
    if (!model) return;

    Campaign* root = model->root<Campaign*>();
    if (!root) return;

    QBuffer b;
    b.open(QBuffer::ReadWrite);


    XmlSerializer s(this);
    s.serialize(root, &b);

    ui->plainTextEdit->setPlainText(b.data());


}


void MainWindow::closeEvent(QCloseEvent *e)
{
    ItemTreeModel* model = qobject_cast<ItemTreeModel*>(ui->treeView->model());
    if (model && model->root())
    {
        on_actionSave_As_triggered();
    }

    QMainWindow::closeEvent(e);
}

void MainWindow::on_actionNew_triggered()
{
    ItemTreeModel* model = qobject_cast<ItemTreeModel*>(ui->treeView->model());
    if (!model) return;


    if (model->root())
    {
        on_actionSave_As_triggered();
        model->root()->deleteLater();
        model->setRoot(0);
    }

    Campaign* root = Campaign::create<Campaign*>(CAMPAIGN_TYPE_ID, this);
    model->setRoot(root);

    onModelChanged();
}

void MainWindow::on_actionOpen_triggered()
{
    ItemTreeModel* model = qobject_cast<ItemTreeModel*>(ui->treeView->model());
    if (!model)
    {
        return;
    }

    if (model->root())
    {
        on_actionSave_As_triggered();
        model->root()->deleteLater();
        model->setRoot(0);
    }

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), QDir::currentPath(), tr("Xml File (*.xml)"));
    if (fileName.isEmpty())
    {
        return;
    }

    QFile file(fileName);
    if (!file.open(QFile::ReadOnly))
    {
        qDebug() << Q_FUNC_INFO << "- Failed to open file!";
        return;
    }

    XmlSerializer s(this);
    Campaign* root = qobject_cast<Campaign*>(s.deserialize(&file));
    if (!root)
    {
        qDebug() << Q_FUNC_INFO << "- Failed to deserialize!";
        return;
    }

    model->setRoot(root);
}


void MainWindow::on_actionSave_As_triggered()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), QDir::currentPath(), tr("Xml File (*.xml)"));
    if (fileName.isEmpty())
    {
        return;
    }

    ItemTreeModel* model = qobject_cast<ItemTreeModel*>(ui->treeView->model());
    if (!model)
    {
        return;
    }


    Campaign* root = model->root<Campaign*>();
    if (!root)
    {
        return;
    }

    QFile file(fileName);
    if (!file.open(QFile::WriteOnly))
    {
        qDebug() << Q_FUNC_INFO << "- Failed to open file!";
        return;
    }

    XmlSerializer s(this);
    s.serialize(root, &file);
}

void MainWindow::on_actionQuit_triggered()
{
    close();
}

void MainWindow::on_actionAdd_triggered()
{
    DTwentyModel* model = qobject_cast<DTwentyModel*>(ui->treeView->model());
    if (!model)
    {
        qWarning() << Q_FUNC_INFO << "D20 Model does not exist!";
        return;
    }

    Campaign* root = model->root<Campaign*>();
    if (!root)
    {
        on_actionNew_triggered();
        root = model->root<Campaign*>();
        if (!root)
        {
            return;
        }
    }

    AddItemDialog dlg(root->types(), this);
    if (dlg.exec() != AddItemDialog::Accepted)
    {
        return;
    }

    int type = dlg.type();

    DataSuite* suite = root->suite(type);
    if (!suite)
    {
        qDebug() << Q_FUNC_INFO << "Suite does not exist!";
        return;
    }

    QModelIndex parent;
    QModelIndexList topLevelIndexes = model->match(model->index(0, 0, QModelIndex()), Qt::DisplayRole, "*", -1, Qt::MatchWildcard);
    foreach (QModelIndex topLevelIndex, topLevelIndexes)
    {
        if (topLevelIndex.internalPointer() != suite)
        {
            continue;
        }

        parent = topLevelIndex;
    }

    if (!parent.isValid())
    {
        qDebug() << Q_FUNC_INFO << "Parent index is invalid!";
        return;
    }

    int row = model->rowCount(parent);

    if (!model->insertRows(row, 1, parent))
    {
        qDebug() << Q_FUNC_INFO << "Failed to insert row!";
        return;
    }

    QModelIndex index = model->index(row, 0, parent);
    if (!index.isValid())
    {
        qDebug() << Q_FUNC_INFO << "Created index is invalid!";
        return;
    }

    ui->treeView->setCurrentIndex(index);
    ui->treeView->scrollTo(index);
    ui->treeView->edit(index);


    onModelChanged();
}


void MainWindow::on_actionRemove_triggered()
{
    QModelIndex index = ui->treeView->currentIndex();
    if (!index.parent().isValid()) return;

    ui->treeView->model()->removeRows(index.row(), 1, index.parent());
    onModelChanged();
}



void MainWindow::on_actionAdd_Field_triggered()
{

}
